Micron Document
🎖️GitЯра🎖️

Node / meshtastic / Meshtastic-Android / files / core / ui / src / androidMain / kotlin / org / meshtastic / core / ui / util / PlatformUtils.kt

Displaying Raw • Download

core/ui/src/androidMain/kotlin/org/meshtastic/core/ui/util/PlatformUtils.kt 01cd54907d62cd90913d3d071b6bc240cae365ef (01cd5490) Text, 22.38 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tf0883e@fileTb4b4b4:Te6edf3SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooManyFunctionsTa5d6ff"Tb4b4b4)

Tff7b72package T7ee787org.meshtastic.core.ui.util

Tff7b72import T7ee787android.bluetooth.BluetoothAdapter
Tff7b72import T7ee787android.bluetooth.BluetoothManager
Tff7b72import T7ee787android.content.ActivityNotFoundException
Tff7b72import T7ee787android.content.BroadcastReceiver
Tff7b72import T7ee787android.content.Context
Tff7b72import T7ee787android.content.Intent
Tff7b72import T7ee787android.content.IntentFilter
Tff7b72import T7ee787android.content.pm.PackageManager
Tff7b72import T7ee787android.net.ConnectivityManager
Tff7b72import T7ee787android.net.Network
Tff7b72import T7ee787android.net.NetworkCapabilities
Tff7b72import T7ee787android.net.NetworkRequest
Tff7b72import T7ee787android.net.Uri
Tff7b72import T7ee787android.os.Handler
Tff7b72import T7ee787android.os.Looper
Tff7b72import T7ee787android.provider.Settings
Tff7b72import T7ee787androidx.activity.compose.LocalActivity
Tff7b72import T7ee787androidx.activity.compose.rememberLauncherForActivityResult
Tff7b72import T7ee787androidx.activity.result.contract.ActivityResultContracts
Tff7b72import T7ee787androidx.compose.runtime.Composable
Tff7b72import T7ee787androidx.compose.runtime.DisposableEffect
Tff7b72import T7ee787androidx.compose.runtime.mutableStateOf
Tff7b72import T7ee787androidx.compose.runtime.remember
Tff7b72import T7ee787androidx.compose.runtime.rememberUpdatedState
Tff7b72import T7ee787androidx.compose.ui.platform.LocalContext
Tff7b72import T7ee787androidx.compose.ui.platform.LocalView
Tff7b72import T7ee787androidx.core.app.ActivityCompat
Tff7b72import T7ee787androidx.core.content.ContextCompat
Tff7b72import T7ee787androidx.core.net.toUri
Tff7b72import T7ee787androidx.lifecycle.Lifecycle
Tff7b72import T7ee787androidx.lifecycle.compose.LifecycleEventEffect
Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787com.eygraber.uri.toAndroidUri
Tff7b72import T7ee787com.eygraber.uri.toKmpUri
Tff7b72import T7ee787kotlinx.coroutines.withContext
Tff7b72import T7ee787org.jetbrains.compose.resources.StringResource
Tff7b72import T7ee787org.jetbrains.compose.resources.getString
Tff7b72import T7ee787org.meshtastic.core.common.gpsDisabled
Tff7b72import T7ee787org.meshtastic.core.common.util.CommonUri
Tff7b72import T7ee787org.meshtastic.core.common.util.ioDispatcher
Tff7b72import T7ee787java.net.URLEncoder

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberOpenNfcSettingsTb4b4b4(Tb4b4b4)Tb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72return Te6edf3rememberTb4b4b4(Te6edf3contextTb4b4b4) Tb4b4b4{
Tb4b4b4{
Tff7b72val Te6edf3intent Tff7b72= Te6edf3IntentTb4b4b4(Te6edf3SettingsTb4b4b4.Te6edf3ACTION_NFC_SETTINGSTb4b4b4)
Te6edf3intentTb4b4b4.Te6edf3flags Tff7b72= Te6edf3IntentTb4b4b4.Te6edf3FLAG_ACTIVITY_NEW_TASK
Te6edf3contextTb4b4b4.Te6edf3startActivityTb4b4b4(Te6edf3intentTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberShowToastTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3suspend Tb4b4b4(Tffa657StringTb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72return Te6edf3rememberTb4b4b4(Te6edf3contextTb4b4b4) Tb4b4b4{ Tb4b4b4{ Te6edf3text Tff7b72-Tff7b72> Te6edf3contextTb4b4b4.Te6edf3showToastTb4b4b4(Te6edf3textTb4b4b4) Tb4b4b4} Tb4b4b4}
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberShowToastResourceTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3suspend Tb4b4b4(Te6edf3StringResourceTb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72return Te6edf3rememberTb4b4b4(Te6edf3contextTb4b4b4) Tb4b4b4{ Tb4b4b4{ Te6edf3stringResource Tff7b72-Tff7b72> Te6edf3contextTb4b4b4.Te6edf3showToastTb4b4b4(Te6edf3getStringTb4b4b4(Te6edf3stringResourceTb4b4b4)Tb4b4b4) Tb4b4b4} Tb4b4b4}
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberOpenMapTb4b4b4(Tb4b4b4)Tb4b4b4: Tb4b4b4(Te6edf3latitudeTb4b4b4: Tffa657DoubleTb4b4b4, Te6edf3longitudeTb4b4b4: Tffa657DoubleTb4b4b4, Te6edf3labelTb4b4b4: Tffa657StringTb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72return Te6edf3rememberTb4b4b4(Te6edf3contextTb4b4b4) Tb4b4b4{
Tb4b4b4{ Te6edf3latTb4b4b4, Te6edf3lonTb4b4b4, Te6edf3label Tff7b72-Tff7b72>
Tff7b72val Te6edf3encodedLabel Tff7b72= Te6edf3URLEncoderTb4b4b4.Te6edf3encodeTb4b4b4(Te6edf3labelTb4b4b4, Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3uri Tff7b72= Ta5d6ff"Ta5d6ffgeo:0,0?q=Tffd700$Te6edf3latTa5d6ff,Tffd700$Te6edf3lonTa5d6ff&z=17&label=Tffd700$Te6edf3encodedLabelTa5d6ff"Tb4b4b4.Te6edf3toUriTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3intent Tff7b72= Te6edf3IntentTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3ACTION_VIEWTb4b4b4, Te6edf3uriTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Te6edf3addFlagsTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3FLAG_ACTIVITY_NEW_TASKTb4b4b4) Tb4b4b4}

Tff7b72try Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3intentTb4b4b4.Te6edf3resolveActivityTb4b4b4(Te6edf3contextTb4b4b4.Te6edf3packageManagerTb4b4b4) Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3contextTb4b4b4.Te6edf3startActivityTb4b4b4(Te6edf3intentTb4b4b4)
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3ActivityNotFoundExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffFailed to open geo intent: Tffd700$Te6edf3exTa5d6ff" Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberOpenUrlTb4b4b4(Tb4b4b4)Tb4b4b4: Tb4b4b4(Te6edf3urlTb4b4b4: Tffa657StringTb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72return Te6edf3rememberTb4b4b4(Te6edf3contextTb4b4b4) Tb4b4b4{
Tb4b4b4{ Te6edf3url Tff7b72-Tff7b72>
Tff7b72try Tb4b4b4{
Tff7b72val Te6edf3intent Tff7b72= Te6edf3IntentTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3ACTION_VIEWTb4b4b4, Te6edf3urlTb4b4b4.Te6edf3toUriTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Te6edf3addFlagsTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3FLAG_ACTIVITY_NEW_TASKTb4b4b4) Tb4b4b4}
Te6edf3contextTb4b4b4.Te6edf3startActivityTb4b4b4(Te6edf3intentTb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3ActivityNotFoundExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffFailed to open URL intent: Tffd700$Te6edf3exTa5d6ff" Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tf0883e@Composable
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffWrappingTa5d6ff"Tb4b4b4)
Tff7b72actual Tff7b72fun Td2a8ffrememberSaveFileLauncherTb4b4b4(
Te6edf3onUriReceivedTb4b4b4: Tb4b4b4(Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3commonTb4b4b4.Te6edf3utilTb4b4b4.Te6edf3CommonUriTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4,
Tb4b4b4)Tb4b4b4: Tb4b4b4(Te6edf3defaultFilenameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3mimeTypeTb4b4b4: Tffa657StringTb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tb4b4b4{
Tff7b72val Te6edf3launcher Tff7b72=
Te6edf3androidxTb4b4b4.Te6edf3activityTb4b4b4.Te6edf3composeTb4b4b4.Te6edf3rememberLauncherForActivityResultTb4b4b4(
Te6edf3androidxTb4b4b4.Te6edf3activityTb4b4b4.Te6edf3resultTb4b4b4.Te6edf3contractTb4b4b4.Te6edf3ActivityResultContractsTb4b4b4.Te6edf3StartActivityForResultTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4) Tb4b4b4{ Te6edf3result Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Te6edf3resultTb4b4b4.Te6edf3resultCode Tff7b72=Tff7b72= Te6edf3androidTb4b4b4.Te6edf3appTb4b4b4.Te6edf3ActivityTb4b4b4.Te6edf3RESULT_OKTb4b4b4) Tb4b4b4{
Te6edf3resultTb4b4b4.Te6edf3dataTff7b72?.Te6edf3dataTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3uri Tff7b72-Tff7b72> Te6edf3onUriReceivedTb4b4b4(Te6edf3uriTb4b4b4.Te6edf3toKmpUriTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tff7b72return Te6edf3rememberTb4b4b4(Te6edf3launcherTb4b4b4) Tb4b4b4{
Tb4b4b4{ Te6edf3defaultFilenameTb4b4b4, Te6edf3mimeType Tff7b72-Tff7b72>
Tff7b72val Te6edf3intent Tff7b72=
Te6edf3IntentTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3ACTION_CREATE_DOCUMENTTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3addCategoryTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3CATEGORY_OPENABLETb4b4b4)
Te6edf3type Tff7b72= Te6edf3mimeType
Te6edf3putExtraTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3EXTRA_TITLETb4b4b4, Te6edf3defaultFilenameTb4b4b4)
Tb4b4b4}
Te6edf3launcherTb4b4b4.Te6edf3launchTb4b4b4(Te6edf3intentTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberOpenFileLauncherTb4b4b4(Te6edf3onUriReceivedTb4b4b4: Tb4b4b4(Te6edf3CommonUri?Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4)Tb4b4b4: Tb4b4b4(Te6edf3mimeTypeTb4b4b4: Tffa657StringTb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tb4b4b4{
Tff7b72val Te6edf3launcher Tff7b72=
Te6edf3rememberLauncherForActivityResultTb4b4b4(Te6edf3ActivityResultContractsTb4b4b4.Te6edf3GetContentTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3uri Tff7b72-Tff7b72>
Te6edf3onUriReceivedTb4b4b4(Te6edf3uriTff7b72?.Te6edf3let Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3toKmpUriTb4b4b4(Tb4b4b4) Tb4b4b4}Tb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3rememberTb4b4b4(Te6edf3launcherTb4b4b4) Tb4b4b4{ Tb4b4b4{ Te6edf3mimeType Tff7b72-Tff7b72> Te6edf3launcherTb4b4b4.Te6edf3launchTb4b4b4(Te6edf3mimeTypeTb4b4b4) Tb4b4b4} Tb4b4b4}
Tb4b4b4}

Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffWrappingTa5d6ff"Tb4b4b4)
Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberReadTextFromUriTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3suspend Tb4b4b4(Te6edf3uriTb4b4b4: Te6edf3CommonUriTb4b4b4, Te6edf3maxCharsTb4b4b4: Tffa657IntTb4b4b4) Tff7b72-Tff7b72> Tffa657String? Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72return Te6edf3rememberTb4b4b4(Te6edf3contextTb4b4b4) Tb4b4b4{
Tb4b4b4{ Te6edf3uriTb4b4b4, Te6edf3maxChars Tff7b72-Tff7b72>
Te6edf3withContextTb4b4b4(Te6edf3ioDispatcherTb4b4b4) Tb4b4b4{
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooGenericExceptionCaughtTa5d6ff"Tb4b4b4)
Tff7b72try Tb4b4b4{
Tff7b72val Te6edf3androidUri Tff7b72= Te6edf3uriTb4b4b4.Te6edf3toAndroidUriTb4b4b4(Tb4b4b4)
Te6edf3contextTb4b4b4.Te6edf3contentResolverTb4b4b4.Te6edf3openInputStreamTb4b4b4(Te6edf3androidUriTb4b4b4)Tff7b72?.Te6edf3use Tb4b4b4{ Te6edf3stream Tff7b72-Tff7b72>
Te6edf3streamTb4b4b4.Te6edf3bufferedReaderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3use Tb4b4b4{ Te6edf3reader Tff7b72-Tff7b72>
Tff7b72val Te6edf3buffer Tff7b72= Te6edf3CharArrayTb4b4b4(Te6edf3maxCharsTb4b4b4)
Tff7b72val Te6edf3read Tff7b72= Te6edf3readerTb4b4b4.Te6edf3readTb4b4b4(Te6edf3bufferTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3read Tff7b72> T79c0ff0Tb4b4b4) Tffa657StringTb4b4b4(Te6edf3bufferTb4b4b4, T79c0ff0Tb4b4b4, Te6edf3readTb4b4b4) Tff7b72else Tff7b72null
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3eTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffFailed to read text from URI: Tffd700$Te6edf3uriTa5d6ff" Tb4b4b4}
Tff7b72null
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffKeepScreenOnTb4b4b4(Te6edf3enabledTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3view Tff7b72= Te6edf3LocalViewTb4b4b4.Te6edf3current
Te6edf3DisposableEffectTb4b4b4(Te6edf3enabledTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3enabledTb4b4b4) Tb4b4b4{
Te6edf3viewTb4b4b4.Te6edf3keepScreenOn Tff7b72= Tff7b72true
Tb4b4b4}
Te6edf3onDispose Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3enabledTb4b4b4) Tb4b4b4{
Te6edf3viewTb4b4b4.Te6edf3keepScreenOn Tff7b72= Tff7b72false
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberOpenLocationSettingsTb4b4b4(Tb4b4b4)Tb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tb4b4b4{
Tff7b72val Te6edf3launcher Tff7b72=
Te6edf3androidxTb4b4b4.Te6edf3activityTb4b4b4.Te6edf3composeTb4b4b4.Te6edf3rememberLauncherForActivityResultTb4b4b4(
Te6edf3androidxTb4b4b4.Te6edf3activityTb4b4b4.Te6edf3resultTb4b4b4.Te6edf3contractTb4b4b4.Te6edf3ActivityResultContractsTb4b4b4.Te6edf3StartActivityForResultTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4) Tb4b4b4{ Te6edf3_ Tff7b72-Tff7b72>
Tb4b4b4}
Tff7b72return Te6edf3rememberTb4b4b4(Te6edf3launcherTb4b4b4) Tb4b4b4{
Tb4b4b4{
Tff7b72try Tb4b4b4{
Te6edf3launcherTb4b4b4.Te6edf3launchTb4b4b4(Te6edf3IntentTb4b4b4(Te6edf3androidTb4b4b4.Te6edf3providerTb4b4b4.Te6edf3SettingsTb4b4b4.Te6edf3ACTION_LOCATION_SOURCE_SETTINGSTb4b4b4)Tb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3ActivityNotFoundExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Te6edf3exTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffNo location settings activity availableTa5d6ff" Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

T8b949e// API level at which ACCESS_LOCAL_NETWORK became a real runtime permission (Android 17 / API 37).
T8b949e// Hardcoded as an integer literal because Build.VERSION_CODES does not yet expose a named constant
T8b949e// for API 37 in the SDK we compile against (current max named constant is VANILLA_ICE_CREAM / API 35).
T8b949e// On older API levels the permission string is unknown to the system and requestPermission() returns
T8b949e// an immediate denial, which would incorrectly disable any caller that disables itself on denial.
Tff7b72private Tff7b72const Tff7b72val Te6edf3LOCAL_NETWORK_PERMISSION_API Tff7b72= T79c0ff3T79c0ff7

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffisGpsDisabledTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72return Te6edf3rememberOnResumeState Tb4b4b4{ Te6edf3contextTb4b4b4.Te6edf3gpsDisabledTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberOpenBluetoothSettingsTb4b4b4(Tb4b4b4)Tb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72return Te6edf3rememberTb4b4b4(Te6edf3contextTb4b4b4) Tb4b4b4{
Tb4b4b4{
Tff7b72try Tb4b4b4{
Te6edf3contextTb4b4b4.Te6edf3startActivityTb4b4b4(
Te6edf3IntentTb4b4b4(Te6edf3SettingsTb4b4b4.Te6edf3ACTION_BLUETOOTH_SETTINGSTb4b4b4)Tb4b4b4.Te6edf3addFlagsTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3FLAG_ACTIVITY_NEW_TASKTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3ActivityNotFoundExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Te6edf3exTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffNo Bluetooth settings activity availableTa5d6ff" Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberOpenWifiSettingsTb4b4b4(Tb4b4b4)Tb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72return Te6edf3rememberTb4b4b4(Te6edf3contextTb4b4b4) Tb4b4b4{
Tb4b4b4{
Tff7b72try Tb4b4b4{
Te6edf3contextTb4b4b4.Te6edf3startActivityTb4b4b4(Te6edf3IntentTb4b4b4(Te6edf3SettingsTb4b4b4.Te6edf3ACTION_WIFI_SETTINGSTb4b4b4)Tb4b4b4.Te6edf3addFlagsTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3FLAG_ACTIVITY_NEW_TASKTb4b4b4)Tb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3ActivityNotFoundExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Te6edf3exTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffNo Wi-Fi settings activity availableTa5d6ff" Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffisBluetoothDisabledTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72return Te6edf3rememberObservedFlagTb4b4b4(
Te6edf3read Tff7b72= Tb4b4b4{
T8b949e// adapter == null means the device has no Bluetooth at all — not "disabled", so don't nag.
Tff7b72val Te6edf3adapter Tff7b72= Tb4b4b4(Te6edf3contextTb4b4b4.Te6edf3getSystemServiceTb4b4b4(Te6edf3ContextTb4b4b4.Te6edf3BLUETOOTH_SERVICETb4b4b4) Tff7b72as? Te6edf3BluetoothManagerTb4b4b4)Tff7b72?.Te6edf3adapter
Te6edf3adapter Tff7b72!Tff7b72= Tff7b72null Tff7b72&Tff7b72& Tff7b72!Te6edf3adapterTb4b4b4.Te6edf3isEnabled
Tb4b4b4}Tb4b4b4,
Te6edf3subscribe Tff7b72= Tb4b4b4{ Te6edf3onChange Tff7b72-Tff7b72>
Tff7b72val Te6edf3receiver Tff7b72=
Tff7b72object Tb4b4b4: T56d364BroadcastReceiverTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72override Tff7b72fun Td2a8ffonReceiveTb4b4b4(Te6edf3receiverContextTb4b4b4: Te6edf3Context?Tb4b4b4, Te6edf3intentTb4b4b4: Te6edf3Intent?Tb4b4b4) Tff7b72= Te6edf3onChangeTb4b4b4(Tb4b4b4)
Tb4b4b4}
T8b949e// ACTION_STATE_CHANGED is a protected system broadcast; NOT_EXPORTED keeps the receiver app-private.
T8b949e// Registered without a Handler, so onReceive is delivered on the main thread.
Te6edf3ContextCompatTb4b4b4.Te6edf3registerReceiverTb4b4b4(
Te6edf3contextTb4b4b4,
Te6edf3receiverTb4b4b4,
Te6edf3IntentFilterTb4b4b4(Te6edf3BluetoothAdapterTb4b4b4.Te6edf3ACTION_STATE_CHANGEDTb4b4b4)Tb4b4b4,
Te6edf3ContextCompatTb4b4b4.Te6edf3RECEIVER_NOT_EXPORTEDTb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3unregister Tff7b72= Tb4b4b4{ Te6edf3contextTb4b4b4.Te6edf3unregisterReceiverTb4b4b4(Te6edf3receiverTb4b4b4) Tb4b4b4}
Te6edf3unregister
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffisWifiUnavailableTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72return Te6edf3rememberObservedFlagTb4b4b4(
Te6edf3read Tff7b72= Tb4b4b4{
Tff7b72val Te6edf3cm Tff7b72= Te6edf3contextTb4b4b4.Te6edf3getSystemServiceTb4b4b4(Te6edf3ContextTb4b4b4.Te6edf3CONNECTIVITY_SERVICETb4b4b4) Tff7b72as? Te6edf3ConnectivityManager
T8b949e// Scan every current network, not just `activeNetwork`: NSD/mDNS only needs *a* LAN, and
T8b949e// Android often keeps cellular as the default route (or leaves Wi-Fi unvalidated), which
T8b949e// previously stranded the banner "on" even after Wi-Fi returned.
Te6edf3cmTff7b72?.Te6edf3hasLocalNetworkTb4b4b4(Tb4b4b4) Tff7b72!Tff7b72= Tff7b72true
Tb4b4b4}Tb4b4b4,
Te6edf3subscribe Tff7b72= Tb4b4b4{ Te6edf3onChange Tff7b72-Tff7b72>
Tff7b72val Te6edf3cm Tff7b72= Te6edf3contextTb4b4b4.Te6edf3getSystemServiceTb4b4b4(Te6edf3ContextTb4b4b4.Te6edf3CONNECTIVITY_SERVICETb4b4b4) Tff7b72as Te6edf3ConnectivityManager
Tff7b72val Te6edf3handler Tff7b72= Te6edf3HandlerTb4b4b4(Te6edf3LooperTb4b4b4.Te6edf3getMainLooperTb4b4b4(Tb4b4b4)Tb4b4b4)
T8b949e// Three separate NetworkRequests are registered so changes to any individual transport
T8b949e// (Wi-Fi, Ethernet, or VPN) independently trigger a re-evaluation of local network
T8b949e// availability. Registering per-transport callbacks fires `onChange` on gain/loss/
T8b949e// capability-change of any Wi-Fi, Ethernet, or VPN network. VPN is tracked alongside the
T8b949e// physical LAN transports because a routed overlay (ZeroTier/Tailscale) is a valid
T8b949e// reachability path for a TCP node; cellular-only is not, so CELLULAR is excluded.
Tff7b72val Te6edf3wifiRequest Tff7b72= Te6edf3NetworkRequestTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3addTransportTypeTb4b4b4(Te6edf3NetworkCapabilitiesTb4b4b4.Te6edf3TRANSPORT_WIFITb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3ethernetRequest Tff7b72=
Te6edf3NetworkRequestTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3addTransportTypeTb4b4b4(Te6edf3NetworkCapabilitiesTb4b4b4.Te6edf3TRANSPORT_ETHERNETTb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3vpnRequest Tff7b72= Te6edf3NetworkRequestTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3addTransportTypeTb4b4b4(Te6edf3NetworkCapabilitiesTb4b4b4.Te6edf3TRANSPORT_VPNTb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3wifiCallback Tff7b72= Te6edf3localNetworkCallbackTb4b4b4(Te6edf3onChangeTb4b4b4)
Tff7b72val Te6edf3ethernetCallback Tff7b72= Te6edf3localNetworkCallbackTb4b4b4(Te6edf3onChangeTb4b4b4)
Tff7b72val Te6edf3vpnCallback Tff7b72= Te6edf3localNetworkCallbackTb4b4b4(Te6edf3onChangeTb4b4b4)
Te6edf3cmTb4b4b4.Te6edf3registerNetworkCallbackTb4b4b4(Te6edf3wifiRequestTb4b4b4, Te6edf3wifiCallbackTb4b4b4, Te6edf3handlerTb4b4b4)
Te6edf3cmTb4b4b4.Te6edf3registerNetworkCallbackTb4b4b4(Te6edf3ethernetRequestTb4b4b4, Te6edf3ethernetCallbackTb4b4b4, Te6edf3handlerTb4b4b4)
Te6edf3cmTb4b4b4.Te6edf3registerNetworkCallbackTb4b4b4(Te6edf3vpnRequestTb4b4b4, Te6edf3vpnCallbackTb4b4b4, Te6edf3handlerTb4b4b4)
Tff7b72val Te6edf3unregister Tff7b72= Tb4b4b4{
Te6edf3cmTb4b4b4.Te6edf3unregisterNetworkCallbackTb4b4b4(Te6edf3wifiCallbackTb4b4b4)
Te6edf3cmTb4b4b4.Te6edf3unregisterNetworkCallbackTb4b4b4(Te6edf3ethernetCallbackTb4b4b4)
Te6edf3cmTb4b4b4.Te6edf3unregisterNetworkCallbackTb4b4b4(Te6edf3vpnCallbackTb4b4b4)
Tb4b4b4}
Te6edf3unregister
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}

T8b949e/**
* Returns `true` if any currently-tracked network carries a Wi-Fi, Ethernet, or VPN transport — the three transports
* that can carry TCP traffic to a Meshtastic node and therefore back the network-scan discovery surfaced by
* `ConnectionsScreen`. Cellular alone is **not** sufficient. Backs the `read` side of `isWifiUnavailable`; extracted so
* the transport reduction can delegate to the platform-agnostic [anyNetworkScanTransportAvailable] helper (which is
* unit-tested in `commonTest`).
*/
T8b949e// ConnectivityManager.allNetworks is deprecated (API 31+) in favor of NetworkCallback-based discovery,
T8b949e// but a synchronous snapshot of active networks is exactly what this transport probe needs. Suppress
T8b949e// until a callback-based rewrite is warranted.
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffDEPRECATIONTa5d6ff"Tb4b4b4)
Tff7b72private Tff7b72fun Te6edf3ConnectivityManagerTb4b4b4.Td2a8ffhasLocalNetworkTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72val Te6edf3transports Tff7b72=
Te6edf3allNetworksTb4b4b4.Te6edf3mapNotNull Tb4b4b4{ Te6edf3network Tff7b72-Tff7b72>
Te6edf3getNetworkCapabilitiesTb4b4b4(Te6edf3networkTb4b4b4)Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3caps Tff7b72-Tff7b72>
Te6edf3NetworkTransportInfoTb4b4b4(
Te6edf3hasWifi Tff7b72= Te6edf3capsTb4b4b4.Te6edf3hasTransportTb4b4b4(Te6edf3NetworkCapabilitiesTb4b4b4.Te6edf3TRANSPORT_WIFITb4b4b4)Tb4b4b4,
Te6edf3hasEthernet Tff7b72= Te6edf3capsTb4b4b4.Te6edf3hasTransportTb4b4b4(Te6edf3NetworkCapabilitiesTb4b4b4.Te6edf3TRANSPORT_ETHERNETTb4b4b4)Tb4b4b4,
Te6edf3hasVpn Tff7b72= Te6edf3capsTb4b4b4.Te6edf3hasTransportTb4b4b4(Te6edf3NetworkCapabilitiesTb4b4b4.Te6edf3TRANSPORT_VPNTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72return Te6edf3anyNetworkScanTransportAvailableTb4b4b4(Te6edf3transportsTb4b4b4)
Tb4b4b4}

T8b949e/**
* Bridges `ConnectivityManager` events to the `rememberObservedFlag` `onChange` trigger. Each callback registration
* gets its own instance so `unregisterNetworkCallback` is symmetric.
*/
Tff7b72private Tff7b72fun Td2a8fflocalNetworkCallbackTb4b4b4(Te6edf3onChangeTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4) Tff7b72= Tff7b72object Tb4b4b4: T56d364ConnectivityManagerTb4b4b4.Te6edf3NetworkCallbackTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72override Tff7b72fun Td2a8ffonAvailableTb4b4b4(Te6edf3networkTb4b4b4: Te6edf3NetworkTb4b4b4) Tff7b72= Te6edf3onChangeTb4b4b4(Tb4b4b4)

Tff7b72override Tff7b72fun Td2a8ffonLostTb4b4b4(Te6edf3networkTb4b4b4: Te6edf3NetworkTb4b4b4) Tff7b72= Te6edf3onChangeTb4b4b4(Tb4b4b4)

Tff7b72override Tff7b72fun Td2a8ffonCapabilitiesChangedTb4b4b4(Te6edf3networkTb4b4b4: Te6edf3NetworkTb4b4b4, Te6edf3networkCapabilitiesTb4b4b4: Te6edf3NetworkCapabilitiesTb4b4b4) Tff7b72= Te6edf3onChangeTb4b4b4(Tb4b4b4)
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberOpenAppSettingsTb4b4b4(Tb4b4b4)Tb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657Unit Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72return Te6edf3rememberTb4b4b4(Te6edf3contextTb4b4b4) Tb4b4b4{
Tb4b4b4{
Tff7b72val Te6edf3intent Tff7b72=
Te6edf3IntentTb4b4b4(Te6edf3SettingsTb4b4b4.Te6edf3ACTION_APPLICATION_DETAILS_SETTINGSTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3data Tff7b72= Te6edf3UriTb4b4b4.Te6edf3fromPartsTb4b4b4(Ta5d6ff"Ta5d6ffpackageTa5d6ff"Tb4b4b4, Te6edf3contextTb4b4b4.Te6edf3packageNameTb4b4b4, Tff7b72nullTb4b4b4)
Te6edf3addFlagsTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3FLAG_ACTIVITY_NEW_TASKTb4b4b4)
Tb4b4b4}
Tff7b72try Tb4b4b4{
Te6edf3contextTb4b4b4.Te6edf3startActivityTb4b4b4(Te6edf3intentTb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3ActivityNotFoundExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Te6edf3exTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffFailed to open app settingsTa5d6ff" Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberLocationPermissionStateTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3PermissionUiState Tff7b72= Te6edf3rememberRuntimePermissionStateTb4b4b4(
Te6edf3permissions Tff7b72=
Te6edf3arrayOfTb4b4b4(
Te6edf3androidTb4b4b4.Te6edf3ManifestTb4b4b4.Te6edf3permissionTb4b4b4.Te6edf3ACCESS_FINE_LOCATIONTb4b4b4,
Te6edf3androidTb4b4b4.Te6edf3ManifestTb4b4b4.Te6edf3permissionTb4b4b4.Te6edf3ACCESS_COARSE_LOCATIONTb4b4b4,
Tb4b4b4)Tb4b4b4,
T8b949e// Coarse-only grants are an accepted degraded mode, so any granted permission counts.
Te6edf3requireAll Tff7b72= Tff7b72falseTb4b4b4,
Tb4b4b4)

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberBluetoothPermissionStateTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3PermissionUiState Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3androidTb4b4b4.Te6edf3osTb4b4b4.Te6edf3BuildTb4b4b4.Te6edf3VERSIONTb4b4b4.Te6edf3SDK_INT Tff7b72< Te6edf3androidTb4b4b4.Te6edf3osTb4b4b4.Te6edf3BuildTb4b4b4.Te6edf3VERSION_CODESTb4b4b4.Te6edf3STb4b4b4) Tb4b4b4{
T8b949e// Pre-Android 12 has no runtime Bluetooth permission — the platform gates BLE scanning on fine location
T8b949e// instead. Reporting "granted" here left a user who declined location with an empty device list and no way to
T8b949e// re-prompt, so surface the permission that actually blocks the scan. Fine specifically: API 29/30 return zero
T8b949e// scan results on a coarse-only grant.
Tff7b72return Te6edf3rememberRuntimePermissionStateTb4b4b4(
Te6edf3permissions Tff7b72= Te6edf3arrayOfTb4b4b4(Te6edf3androidTb4b4b4.Te6edf3ManifestTb4b4b4.Te6edf3permissionTb4b4b4.Te6edf3ACCESS_FINE_LOCATIONTb4b4b4)Tb4b4b4,
Te6edf3requireAll Tff7b72= Tff7b72trueTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3rememberRuntimePermissionStateTb4b4b4(
Te6edf3permissions Tff7b72=
Te6edf3arrayOfTb4b4b4(Te6edf3androidTb4b4b4.Te6edf3ManifestTb4b4b4.Te6edf3permissionTb4b4b4.Te6edf3BLUETOOTH_SCANTb4b4b4, Te6edf3androidTb4b4b4.Te6edf3ManifestTb4b4b4.Te6edf3permissionTb4b4b4.Te6edf3BLUETOOTH_CONNECTTb4b4b4)Tb4b4b4,
Te6edf3requireAll Tff7b72= Tff7b72trueTb4b4b4,
Tb4b4b4)
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberNotificationPermissionStateTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3PermissionUiState Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3androidTb4b4b4.Te6edf3osTb4b4b4.Te6edf3BuildTb4b4b4.Te6edf3VERSIONTb4b4b4.Te6edf3SDK_INT Tff7b72< Te6edf3androidTb4b4b4.Te6edf3osTb4b4b4.Te6edf3BuildTb4b4b4.Te6edf3VERSION_CODESTb4b4b4.Te6edf3TIRAMISUTb4b4b4) Tb4b4b4{
T8b949e// Pre-Android 13, no runtime notification permission required.
Tff7b72return Te6edf3rememberGrantedPermissionStateTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3rememberRuntimePermissionStateTb4b4b4(
Te6edf3permissions Tff7b72= Te6edf3arrayOfTb4b4b4(Te6edf3androidTb4b4b4.Te6edf3ManifestTb4b4b4.Te6edf3permissionTb4b4b4.Te6edf3POST_NOTIFICATIONSTb4b4b4)Tb4b4b4,
Te6edf3requireAll Tff7b72= Tff7b72trueTb4b4b4,
Tb4b4b4)
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberLocalNetworkPermissionStateTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3PermissionUiState Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3androidTb4b4b4.Te6edf3osTb4b4b4.Te6edf3BuildTb4b4b4.Te6edf3VERSIONTb4b4b4.Te6edf3SDK_INT Tff7b72< Te6edf3LOCAL_NETWORK_PERMISSION_APITb4b4b4) Tb4b4b4{
T8b949e// Pre-Android 17, ACCESS_LOCAL_NETWORK is implicit via INTERNET; treat as granted.
Tff7b72return Te6edf3rememberGrantedPermissionStateTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3rememberRuntimePermissionStateTb4b4b4(
Te6edf3permissions Tff7b72= Te6edf3arrayOfTb4b4b4(Te6edf3androidTb4b4b4.Te6edf3ManifestTb4b4b4.Te6edf3permissionTb4b4b4.Te6edf3ACCESS_LOCAL_NETWORKTb4b4b4)Tb4b4b4,
Te6edf3requireAll Tff7b72= Tff7b72trueTb4b4b4,
Tb4b4b4)
Tb4b4b4}

Tf0883e@Composable
Tff7b72actual Tff7b72fun Td2a8ffrememberCameraPermissionStateTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3PermissionUiState Tff7b72=
Te6edf3rememberRuntimePermissionStateTb4b4b4(Te6edf3permissions Tff7b72= Te6edf3arrayOfTb4b4b4(Te6edf3androidTb4b4b4.Te6edf3ManifestTb4b4b4.Te6edf3permissionTb4b4b4.Te6edf3CAMERATb4b4b4)Tb4b4b4, Te6edf3requireAll Tff7b72= Tff7b72trueTb4b4b4)

T8b949e/** A constant [PermissionUiState] for API levels where the permission is not gated at runtime. */
Tf0883e@Composable Tff7b72private Tff7b72fun Td2a8ffrememberGrantedPermissionStateTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3PermissionUiState Tff7b72= Te6edf3remember Tb4b4b4{ Te6edf3grantedPermissionUiStateTb4b4b4(Tb4b4b4) Tb4b4b4}

T8b949e/**
* Shared engine behind every `rememberXxxPermissionState()`. Computes the [PermissionStatus] from the live grant state,
* the persisted "has-been-requested" flag, and `shouldShowRequestPermissionRationale`, refreshing on `ON_RESUME`
* (return from settings) and immediately after a request completes.
*
* @param requireAll when true, all [permissions] must be granted to count as [PermissionStatus.GRANTED]; when false,
* any single grant suffices (used by location so a coarse-only grant is accepted — R7).
*/
Tf0883e@Composable
Tff7b72private Tff7b72fun Td2a8ffrememberRuntimePermissionStateTb4b4b4(Te6edf3permissionsTb4b4b4: Te6edf3ArrayTff7b72<Tffa657StringTff7b72>Tb4b4b4, Te6edf3requireAllTb4b4b4: Tffa657BooleanTb4b4b4)Tb4b4b4: Te6edf3PermissionUiState Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72val Te6edf3activity Tff7b72= Te6edf3LocalActivityTb4b4b4.Te6edf3current
Tff7b72val Te6edf3tracker Tff7b72= Te6edf3rememberTb4b4b4(Te6edf3contextTb4b4b4) Tb4b4b4{ Te6edf3PermissionRequestTrackerTb4b4b4(Te6edf3contextTb4b4b4) Tb4b4b4}
Tff7b72val Te6edf3openAppSettings Tff7b72= Te6edf3rememberOpenAppSettingsTb4b4b4(Tb4b4b4)
T8b949e// The permission whose rationale + requested flag represents the group.
Tff7b72val Te6edf3primaryPermission Tff7b72= Te6edf3permissionsTb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)

Tff7b72fun Td2a8ffcomputeTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3PermissionStatus Tb4b4b4{
Tff7b72val Te6edf3granted Tff7b72=
Te6edf3isPermissionGroupGrantedTb4b4b4(
Te6edf3results Tff7b72=
Te6edf3permissionsTb4b4b4.Te6edf3map Tb4b4b4{
Te6edf3ContextCompatTb4b4b4.Te6edf3checkSelfPermissionTb4b4b4(Te6edf3contextTb4b4b4, Tffa657itTb4b4b4) Tff7b72=Tff7b72= Te6edf3PackageManagerTb4b4b4.Te6edf3PERMISSION_GRANTED
Tb4b4b4}Tb4b4b4,
Te6edf3requireAll Tff7b72= Te6edf3requireAllTb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3shouldShowRationale Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3activity Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3ActivityCompatTb4b4b4.Te6edf3shouldShowRequestPermissionRationaleTb4b4b4(Te6edf3activityTb4b4b4, Te6edf3primaryPermissionTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// No Activity to query (e.g. a non-Activity-hosted composition). Assume a rationale is still warranted
T8b949e// rather than risk a false PERMANENTLY_DENIED that would strand the user with only a settings link.
Tff7b72true
Tb4b4b4}
Tff7b72return Te6edf3computePermissionStatusTb4b4b4(
Te6edf3granted Tff7b72= Te6edf3grantedTb4b4b4,
Te6edf3hasRequested Tff7b72= Te6edf3trackerTb4b4b4.Te6edf3hasRequestedTb4b4b4(Te6edf3primaryPermissionTb4b4b4)Tb4b4b4,
Te6edf3shouldShowRationale Tff7b72= Te6edf3shouldShowRationaleTb4b4b4,
Tb4b4b4)
Tb4b4b4}

Tff7b72val Te6edf3statusState Tff7b72= Te6edf3remember Tb4b4b4{ Te6edf3mutableStateOfTb4b4b4(Te6edf3computeTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4}
Tff7b72val Te6edf3launcher Tff7b72=
Te6edf3rememberLauncherForActivityResultTb4b4b4(Te6edf3ActivityResultContractsTb4b4b4.Te6edf3RequestMultiplePermissionsTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3_ Tff7b72-Tff7b72>
T8b949e// The OS has now adjudicated the request; only here is it true that we have asked the user. The result
T8b949e// callback runs on the main thread, so updating the state directly here is safe and recomposes the caller.
Te6edf3trackerTb4b4b4.Te6edf3markRequestedTb4b4b4(Te6edf3primaryPermissionTb4b4b4)
Te6edf3statusStateTb4b4b4.Te6edf3value Tff7b72= Te6edf3computeTb4b4b4(Tb4b4b4)
Tb4b4b4}
Te6edf3LifecycleEventEffectTb4b4b4(Te6edf3LifecycleTb4b4b4.Te6edf3EventTb4b4b4.Te6edf3ON_RESUMETb4b4b4) Tb4b4b4{ Te6edf3statusStateTb4b4b4.Te6edf3value Tff7b72= Te6edf3computeTb4b4b4(Tb4b4b4) Tb4b4b4}

Tff7b72val Te6edf3request Tff7b72= Te6edf3rememberTb4b4b4(Te6edf3launcherTb4b4b4) Tb4b4b4{ Tb4b4b4{ Te6edf3launcherTb4b4b4.Te6edf3launchTb4b4b4(Te6edf3permissionsTb4b4b4) Tb4b4b4} Tb4b4b4}
Tff7b72return Te6edf3PermissionUiStateTb4b4b4(Te6edf3status Tff7b72= Te6edf3statusStateTb4b4b4.Te6edf3valueTb4b4b4, Te6edf3request Tff7b72= Te6edf3requestTb4b4b4, Te6edf3openAppSettings Tff7b72= Te6edf3openAppSettingsTb4b4b4)
Tb4b4b4}

T8b949e/**
* Remembers a boolean derived from [read], kept live by an observer registered via [subscribe] for the duration of the
* composition. [subscribe] receives an `onChange` callback to invoke whenever the underlying state may have changed and
* must return a teardown function. The value is re-seeded via [read] at registration, so it is correct even before the
* first event arrives. Used for adapter/connectivity state that changes outside the activity lifecycle (e.g. toggling
* Bluetooth or Wi-Fi from the quick-settings shade).
*/
Tf0883e@Composable
Tff7b72private Tff7b72fun Td2a8ffrememberObservedFlagTb4b4b4(Te6edf3readTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657BooleanTb4b4b4, Te6edf3subscribeTb4b4b4: Tb4b4b4(Te6edf3onChangeTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4) Tff7b72-Tff7b72> Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72val Te6edf3currentRead Tff7b72= Te6edf3rememberUpdatedStateTb4b4b4(Te6edf3readTb4b4b4)
Tff7b72val Te6edf3currentSubscribe Tff7b72= Te6edf3rememberUpdatedStateTb4b4b4(Te6edf3subscribeTb4b4b4)
Tff7b72val Te6edf3state Tff7b72= Te6edf3remember Tb4b4b4{ Te6edf3mutableStateOfTb4b4b4(Te6edf3readTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4}
Te6edf3DisposableEffectTb4b4b4(Tffa657UnitTb4b4b4) Tb4b4b4{
Te6edf3stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3currentReadTb4b4b4.Te6edf3valueTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3unsubscribe Tff7b72= Te6edf3currentSubscribeTb4b4b4.Te6edf3value Tb4b4b4{ Te6edf3stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3currentReadTb4b4b4.Te6edf3valueTb4b4b4(Tb4b4b4) Tb4b4b4}
Te6edf3onDispose Tb4b4b4{ Te6edf3unsubscribeTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72return Te6edf3stateTb4b4b4.Te6edf3value
Tb4b4b4}

T8b949e/**
* Remembers a boolean state that is re-evaluated on each [Lifecycle.Event.ON_RESUME], ensuring the value stays fresh
* when the user returns from a permission dialog or system settings screen.
*/
Tf0883e@Composable
Tff7b72private Tff7b72fun Td2a8ffrememberOnResumeStateTb4b4b4(Te6edf3checkTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657BooleanTb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72val Te6edf3state Tff7b72= Te6edf3remember Tb4b4b4{ Te6edf3mutableStateOfTb4b4b4(Te6edf3checkTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4}
Te6edf3LifecycleEventEffectTb4b4b4(Te6edf3LifecycleTb4b4b4.Te6edf3EventTb4b4b4.Te6edf3ON_RESUMETb4b4b4) Tb4b4b4{ Te6edf3stateTb4b4b4.Te6edf3value Tff7b72= Te6edf3checkTb4b4b4(Tb4b4b4) Tb4b4b4}
Tff7b72return Te6edf3stateTb4b4b4.Te6edf3value
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.12s